package fictional.GUI;

import fictional.Common.*;

import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import org.jdesktop.application.TaskMonitor;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.net.MalformedURLException;
import java.net.URL;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;

import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.WindowConstants;

import org.jdesktop.application.Application;
import org.jdesktop.application.ApplicationContext;
import org.jdesktop.application.TaskService;

/**
 * The main GUI class for the application. 
 */
@SuppressWarnings("serial")
public class GUI extends javax.swing.JFrame {

	private CharacterItem displayedCharacter;
	private CharacterItem loggedInCharacter;
	private boolean isSameCharacter;
	private IBL BL;
	private final int DISPLAYED_FRIENDS = 5;
	public static final int EDIT_FRIENDS = 0;
	public static final int ADD_FRIENDS = 1;
	public static final int SEARCH_FRIENDS = 2;
	public static final int VIEW_FRIENDS = 3;
	private TaskMonitor taskMonitor;
	private TaskService taskService;
	private List<DrawData> drawDataList;
	private BusyIconPopup busyIconPopup;
	private ArrayList<ShortCharacterItem> friendRequests;
	private FriendRequests friendRequestsItem;
	private Wall wall;
	private Messages privateMessages;
	private DefaultTask currentlyRunningTask;
	private Response currentResponse;
	private Login login;
	private boolean toDraw;
	private Pokes pokes;
	private FriendRequests friendRequestsSent;
	private boolean isEnabled = true;

	public GUI(CharacterItem character, Login login, IBL BL) {
		this.login = login;
		loggedInCharacter = character;
		displayedCharacter = character;
		this.BL = BL;
		drawDataList = new LinkedList<DrawData>();

		initWindowLookAndFeel();
		initLayout();
		initHeader();

		changeCurrentlyDisplayedCharacter(character);

		ApplicationContext appC = Application.getInstance().getContext();
		taskMonitor = appC.getTaskMonitor();
		taskService = appC.getTaskService();

		busyIconPopup = new BusyIconPopup();

		TaskMonitor taskMonitor = this.taskMonitor;
		taskMonitor
				.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
					public void propertyChange(
							java.beans.PropertyChangeEvent evt) {
						if (currentlyRunningTask == null) {
							return;
						}
						String propertyName = evt.getPropertyName();
						if ("started".equals(propertyName)) 
						{
							startBusy();
						} 
						else if ("done".equals(propertyName)) 
						{
							stopBusy();
							if (!currentlyRunningTask.isSuccessful()) 
							{
								if (!currentlyRunningTask.isActionDone()) 
								{
									if (currentlyRunningTask.response.getException() instanceof SQLException)
									{
										SQLException sqlException = (SQLException)currentlyRunningTask.response.getException();
										if (sqlException.getSQLState().equals("08003"))
										{
											// the connection to database is closed
											doInCaseOfDisconnection();
										}
										else
										{
											currentlyRunningTask.doInCaseOfFail();
										}
									}
									else
									{
										currentlyRunningTask.doInCaseOfFail();
									}
								}
							} 
							else if (!currentlyRunningTask.isActionDone()) 
							{
								currentlyRunningTask.doInCaseOfSuccess();
							}
							
							if (!isEnabled)
							{
								GUI.this.setEnabled(false);
							}
						}
					}
				});
	}
	
	public void setIsEnabled(boolean isEnabled)
	{
		this.isEnabled = isEnabled;
	}
	
	public void setToDraw(boolean toDraw)
	{
		this.toDraw = toDraw;
	}

	public void changeCurrentlyDisplayedCharacter(CharacterItem character) {
		drawDataList = new LinkedList<DrawData>();
		toDraw = false;

		displayedCharacter = character;
		
		if (displayedCharacter.getId() == loggedInCharacter.getId()) {
			isSameCharacter = true;
			displayedCharacter = loggedInCharacter;
		} else {
			isSameCharacter = false;
		}

		initRightPanel();
		initLeftPanel();

		rightPanel.revalidate();
		rightPanel.repaint();
		leftPanel.revalidate();
		leftPanel.repaint();

		(new ImageLoader(drawDataList)).execute();
	}

	private void initLayout() {
		
		initComponents();
		
		initLayoutHeader();
		
		initLayoutRightPanel();
		
		initLayoutLeftPanel();

		pack();
	}

	private void initLayoutLeftPanel() {
		
		// --------------- //
		// START LEFT PANEL
		
		GridBagConstraints cons = new GridBagConstraints();

		leftPanel.setBackground(new Color(252, 251, 251));
		leftPanel.setMaximumSize(null);
		leftPanel.setPreferredSize(new Dimension(450, 660));

		GridBagLayout leftPanelLayout = new GridBagLayout();
		leftPanel.setLayout(leftPanelLayout);

		leftPanelTextLabel.setFont(new java.awt.Font("Tahoma", 1, 14));
		leftPanelTextLabel.setForeground(new java.awt.Color(102, 102, 102));
		leftPanelTextLabel.setText("Want to say something?");

		cons.gridx = 0;
		cons.fill = GridBagConstraints.BOTH;
		cons.weightx = 1.0;
		cons.insets = new Insets(10, 15, 5, 15);
		leftPanel.add(leftPanelTextLabel, cons);

		leftPanelTextArea.setBackground(new java.awt.Color(244, 242, 242));
		leftPanelTextArea.setMinimumSize(new Dimension(400, 70));
		leftPanelTextArea.setLineWrap(true);
		leftPanelTextArea.setRows(4);
		leftPanelTextArea.setAutoscrolls(false);
		leftPanelTextArea.setFont(new java.awt.Font("Tahoma", 0, 13));
		leftPanelTextArea.setBorder(BorderFactory
				.createLineBorder(new java.awt.Color(223, 212, 212)));

		cons.gridy = 1;
		cons.insets = new Insets(0, 15, 10, 15);
		//cons.ipady = 50;
		leftPanel.add(leftPanelTextArea, cons);

		leftPanelButton.setText("Share");
		leftPanelButton.addMouseListener(new java.awt.event.MouseAdapter() {
			public void mouseClicked(java.awt.event.MouseEvent evt) {
				leftPanelButtonMouseClicked(evt);
			}
		});

		cons.gridy = 2;
		cons.ipady = 0;
		cons.anchor = GridBagConstraints.EAST;
		cons.fill = GridBagConstraints.NONE;
		leftPanel.add(leftPanelButton, cons);

		leftPanelTabbedPane
				.addChangeListener(new javax.swing.event.ChangeListener() {
					public void stateChanged(javax.swing.event.ChangeEvent evt) {
						leftPanelTabbedPaneStateChanged(evt);
					}
				});

		wallScrollPane.setBackground(new java.awt.Color(255, 255, 255));
		wallScrollPane.setBorder(null);

		wallPanel.setBackground(new java.awt.Color(255, 255, 255));
		wallPanel.setLayout(new java.awt.GridBagLayout());
		wallScrollPane.setViewportView(wallPanel);

		leftPanelTabbedPane.addTab("Wall", wallScrollPane);

		picturesScrollPane.setBackground(new java.awt.Color(255, 255, 255));
		picturesScrollPane.setBorder(null);

		picturesPanel.setBackground(new java.awt.Color(255, 255, 255));
		picturesPanel.setLayout(new java.awt.GridBagLayout());
		picturesScrollPane.setViewportView(picturesPanel);

		leftPanelTabbedPane.addTab("Pictures", picturesScrollPane);

		cons.gridy = 3;
		cons.weighty = 1.0;
		cons.insets = new Insets(5, 0, 0, 0);
		cons.fill = GridBagConstraints.BOTH;
		leftPanel.add(leftPanelTabbedPane, cons);

		getContentPane().add(leftPanel, java.awt.BorderLayout.WEST);

		// END LEFT PANEL
		
	}

	private void initLayoutRightPanel() 
	{
		// --------------- //
		// START RIGHT PANEL //
		
		GridBagConstraints cons = new GridBagConstraints();

		rightPanel.setBackground(new Color(241, 245, 245));
		rightPanel.setPreferredSize(new Dimension(450, 660));

		GridBagLayout rightPanelLayout = new GridBagLayout();
		rightPanel.setLayout(rightPanelLayout);
		
		profileImagePanel.setBackground(new Color(241, 245, 245));
		profileImagePanel.setPreferredSize(new Dimension(150, 190));
		profileImagePanel.setMinimumSize(new Dimension(150, 190));

		cons.gridx = 0;
		cons.gridy = 0;
		cons.weighty = 0.0;
		cons.weightx = 0.0;
		cons.fill = GridBagConstraints.BOTH;
		cons.insets = new Insets(10, 20, 0, 0);
		rightPanel.add(profileImagePanel, cons);

		GridBagLayout characterInfoPanelLayout = new GridBagLayout();
		characterInfoPanel.setLayout(characterInfoPanelLayout);
		characterInfoPanel.setBackground(new Color(241, 245, 245));

		nameLabel.setFont(new java.awt.Font("Tahoma", 1, 24));
		nameLabel.setText("name\nexample");

		cons.gridheight = 1;
		cons.gridx = 1;
		cons.gridwidth = 4;
		cons.insets = new Insets(20, 10, 5, 0);
		characterInfoPanel.add(nameLabel, cons);

		genderIconLabel.setIcon(new ImageIcon(getClass().getResource(
				"/fictional/GUI/resources/genderIconLabelImage.png"))); 
		genderIconLabel.setToolTipText("Gender");

		cons.gridwidth = 1;
		cons.gridx = 1;
		cons.gridy = 1;
		cons.insets = new Insets(10, 10, 0, 0);
		characterInfoPanel.add(genderIconLabel, cons);

		genderLabel.setText("unknown");

		cons.gridx = 2;
		cons.insets = new Insets(10, 10, 0, 20);
		characterInfoPanel.add(genderLabel, cons);

		romanticIconLabel.setIcon(new ImageIcon(getClass().getResource(
				"/fictional/GUI/resources/heart.png"))); 
		romanticIconLabel.setToolTipText("Romatically involved with...");

		cons.gridx = 3;
		cons.insets = new Insets(10, 10, 0, 0);
		characterInfoPanel.add(romanticIconLabel, cons);

		romanticLabel.setText("unknown");

		cons.gridx = 4;
		cons.insets = new Insets(10, 10, 0, 0);
		cons.weightx = 1.0;
		characterInfoPanel.add(romanticLabel, cons);

		speciesIconLabel.setIcon(new ImageIcon(getClass().getResource(
				"/fictional/GUI/resources/speciesIconLabelImage.gif"))); 
		speciesIconLabel.setToolTipText("Species");

		cons.gridx = 1;
		cons.gridy = 2;
		cons.weightx = 0.0;
		cons.insets = new Insets(10, 10, 0, 0);
		characterInfoPanel.add(speciesIconLabel, cons);

		speciesLabel.setText("unknown");

		cons.gridx = 2;
		cons.insets = new Insets(10, 10, 0, 20);
		characterInfoPanel.add(speciesLabel, cons);

		birthplaceIconLabel.setIcon(new ImageIcon(getClass().getResource(
				"/fictional/GUI/resources/date.png"))); 
		birthplaceIconLabel.setToolTipText("Birth Place");

		cons.gridx = 3;
		cons.insets = new Insets(10, 10, 0, 0);
		characterInfoPanel.add(birthplaceIconLabel, cons);

		birthplaceLabel.setText("unknown");

		cons.gridx = 4;
		cons.insets = new Insets(10, 10, 0, 0);
		cons.weightx = 1.0;
		characterInfoPanel.add(birthplaceLabel, cons);

		organizationIconLabel.setIcon(new ImageIcon(getClass().getResource(
				"/fictional/GUI/resources/briefcase.png"))); 
		organizationIconLabel.setToolTipText("Organizations");

		cons.gridx = 1;
		cons.gridy = 3;
		cons.insets = new Insets(10, 10, 0, 0);
		cons.weightx = 0.0;
		characterInfoPanel.add(organizationIconLabel, cons);

		organizationLabel.setText("unknown");

		cons.gridx = 2;
		cons.gridwidth = 3;
		cons.weightx = 1.0;
		cons.insets = new Insets(10, 10, 0, 20);
		characterInfoPanel.add(organizationLabel, cons);

		powersIconLabel.setIcon(new ImageIcon(getClass().getResource(
				"/fictional/GUI/resources/lightning.png"))); 
		powersIconLabel.setToolTipText("Super Powers");

		cons.gridx = 1;
		cons.gridy = 4;
		cons.gridwidth = 1;
		cons.weightx = 0.0;
		cons.insets = new Insets(10, 10, 0, 0);
		characterInfoPanel.add(powersIconLabel, cons);

		powersLabel.setText("unknown");
		
		cons.gridx = 2;
		cons.weightx = 1.0;
		cons.gridy = 4;
		cons.gridwidth = 3;
		cons.insets = new Insets(10, 10, 0, 20);
		characterInfoPanel.add(powersLabel, cons);
		
		occupationsIconLabel.setIcon(new ImageIcon(getClass().getResource(
		"/fictional/GUI/resources/wrench.png"))); 
		occupationsIconLabel.setToolTipText("Occupations");

		cons.gridx = 1;
		cons.gridy = 5;
		cons.gridwidth = 1;
		cons.weightx = 0.0;
		cons.insets = new Insets(10, 10, 0, 0);
		characterInfoPanel.add(occupationsIconLabel, cons);

		occupationsLabel.setText("unknown");

		cons.gridx = 2;
		cons.weightx = 1.0;
		cons.gridy = 5;
		cons.gridwidth = 3;
		cons.insets = new Insets(10, 10, 0, 20);
		characterInfoPanel.add(occupationsLabel, cons);

		cons.gridx = 1;
		cons.gridy = 0;
		cons.weightx = 1.0;
		cons.gridwidth = 1;
		cons.insets = new Insets(10, 10, 0, 0);

		rightPanel.add(characterInfoPanel, cons);
		
		statusTextField.setFont(new java.awt.Font("Arial", 2, 14));
		statusTextField.setBorder(null);
		statusTextField.setBackground(new java.awt.Color(241, 245, 245));

		editStatusLabel.setCursor(new java.awt.Cursor(
				java.awt.Cursor.HAND_CURSOR));
		editStatusLabel.addMouseListener(new java.awt.event.MouseAdapter() {
			public void mouseClicked(java.awt.event.MouseEvent evt) {
				editStatusMouseClicked();
			}
		});

		editStatusLabel.setIcon(new ImageIcon(getClass().getResource(
				"/fictional/GUI/resources/pencil.png")));
		editStatusLabel.setToolTipText("Edit Status");
		
		cons.gridx = 0;
		cons.gridy = 2;
		cons.gridwidth = 2;
		cons.insets = new Insets(25, 10, 10, 10);
		rightPanel.add(rightPanelSeperator4, cons);

		statusLabel.setBackground(new java.awt.Color(225, 237, 237));
		statusLabel.setOpaque(true);
		statusLabel.setText("STATUS");
		statusLabel.setFont(new Font("Tahoma", Font.BOLD, 11));

		cons.gridx = 0;
		cons.gridy = 3;
		cons.insets = new Insets(0, 10, 0, 10);
		rightPanel.add(statusLabel, cons);
		
		statusPanel.setPreferredSize(new java.awt.Dimension(430, 30));
		statusPanel.setBackground(new java.awt.Color(241, 245, 245));
		statusPanel.setLayout(new GridBagLayout());

		cons.gridx = 0;
		cons.gridy = 4;
		cons.insets = new Insets(0, 10, 10, 10);
		cons.weightx = 1.0;
		cons.gridwidth = 2;
		rightPanel.add(statusPanel, cons);

		cons.gridx = 0;
		cons.gridy = 5;
		cons.gridwidth = 2;
		cons.insets = new Insets(0, 10, 10, 10);
		rightPanel.add(rightPanelSeperator1, cons);

		friendsLabel.setBackground(new java.awt.Color(225, 237, 237));
		friendsLabel.setOpaque(true);

		cons.gridx = 0;
		cons.gridy = 6;
		cons.insets = new Insets(0, 10, 0, 10);
		rightPanel.add(friendsLabel, cons);

		friendsPanel.setPreferredSize(new java.awt.Dimension(400, 65));
		friendsPanel.setMinimumSize(new java.awt.Dimension(400, 65));
		friendsPanel.setLayout(new java.awt.FlowLayout(
				java.awt.FlowLayout.LEFT, 10, 10));
		friendsPanel.setBackground(new java.awt.Color(241, 245, 245));

		cons.gridy = 7;
		rightPanel.add(friendsPanel, cons);
		
        viewAllFriendsButton.setText("View All");
        viewAllFriendsButton.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                viewAllFriendsButtonMouseClicked(evt);
            }
        });

		cons.gridx = 0;
		cons.gridwidth = 2;
		cons.gridy = 8;
		cons.insets = new Insets(10, 10, 10, 10);
		rightPanel.add(rightPanelSeperator2, cons);

		familyLabel.setBackground(new java.awt.Color(225, 237, 237));
		familyLabel.setText("FAMILY");
		familyLabel.setOpaque(true);
		familyLabel.setFont(new Font("Tahoma", Font.BOLD, 11));

		cons.gridx = 0;
		cons.gridy = 9;
		cons.insets = new Insets(0, 10, 0, 10);
		rightPanel.add(familyLabel, cons);

		familyPanel.setPreferredSize(new java.awt.Dimension(400, 65));
		familyPanel.setMinimumSize(new java.awt.Dimension(400, 65));
		familyPanel.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT,
				10, 10));
		familyPanel.setBackground(new java.awt.Color(241, 245, 245));

		cons.gridy = 10;
		rightPanel.add(familyPanel, cons);
		
        viewAllFamilyButton.setText("View All");
        viewAllFamilyButton.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                viewAllFamilyButtonMouseClicked(evt);
            }
        });

		cons.gridx = 0;
		cons.gridwidth = 2;
		cons.gridy = 11;
		cons.insets = new Insets(10, 10, 10, 10);
		rightPanel.add(rightPanelSeperator3, cons);
		
		// set about me panel and buttons (poke, message, add friend) panel
		
		JLabel aboutLabel = new JLabel();
		
		aboutLabel.setBackground(new java.awt.Color(225, 237, 237));
		aboutLabel.setText("ABOUT");
		aboutLabel.setOpaque(true);
		aboutLabel.setFont(new Font("Tahoma", Font.BOLD, 11));
		
		cons.gridx = 0;
		cons.gridy = 12;
		cons.insets = new Insets(0, 10, 0, 10);
		rightPanel.add(aboutLabel, cons);
		
		articlePanel.setBackground(new java.awt.Color(241, 245, 245));
		articlePanel.setLayout(new java.awt.GridBagLayout());
		articlePanel.setPreferredSize(new java.awt.Dimension(400, 80));
		articlePanel.setMinimumSize(new Dimension(400, 80));
		
		cons.gridy = 13;
		cons.weighty = 1.0;
		cons.insets = new Insets(0, 10, 0, 10);
		rightPanel.add(articlePanel, cons);
		
		cons.gridx = 0;
		cons.gridy = 14;
		cons.gridwidth = 2;
		cons.weighty = 0.0;
		cons.insets = new Insets(0, 10, 10, 10);
		rightPanel.add(rightPanelSeperator5, cons);
		
		pokeMessagePanel.setBackground(new java.awt.Color(241, 245, 245));
		pokeMessagePanel.setLayout(new java.awt.GridBagLayout());

		pokeButton.setIcon(new ImageIcon(getClass().getResource(
				"/fictional/GUI/resources/poke.png")));
		pokeButton.setText("Poke");
		pokeButton.setPreferredSize(new Dimension(110, 25));
		pokeButton.addMouseListener(new java.awt.event.MouseAdapter()
        {
            public void mouseClicked(java.awt.event.MouseEvent evt)
            {
            	pokeCharacter(displayedCharacter);
            }
        });
		
		messageButton.setIcon(new ImageIcon(getClass().getResource(
				"/fictional/GUI/resources/comments.png")));
		messageButton.setText("Message");
		messageButton.setPreferredSize(new Dimension(110, 25));
		messageButton.addMouseListener(new java.awt.event.MouseAdapter()
        {
            public void mouseClicked(java.awt.event.MouseEvent evt)
            {
            	sendMessageButtonMouseClicked(evt, displayedCharacter);
            }
        });
		
		addFriendButton.setIcon(new ImageIcon(getClass().getResource(
		"/fictional/GUI/resources/group.png")));
		addFriendButton.setText("Add Friend");
		addFriendButton.setPreferredSize(new Dimension(110, 25));
		addFriendButton.addMouseListener(new java.awt.event.MouseAdapter()
        {
            public void mouseClicked(java.awt.event.MouseEvent evt)
            {
            	if (addFriendButton.isEnabled())
            	{
                	sendFriendRequest(addFriendButton, displayedCharacter);
            	}
            }
        });
		
		cons.gridy = 15;
		cons.insets = new Insets(0, 10, 20, 10);
		rightPanel.add(pokeMessagePanel, cons);
		
		getContentPane().add(rightPanel, java.awt.BorderLayout.EAST);
		
		// END RIGHT PANEL
	}

	private void initLayoutHeader() {
		
		// START HEADER

		headerPanel.setBackground(new java.awt.Color(209, 224, 224));
		headerPanel.setPreferredSize(new java.awt.Dimension(900, 40));

		GridBagLayout headerPanelLayout = new GridBagLayout();
		headerPanel.setLayout(headerPanelLayout);
		GridBagConstraints cons = new GridBagConstraints();

		logoLabel.setIcon(new ImageIcon(getClass().getResource(
				"/fictional/GUI/resources/logo.png"))); 

		cons.gridx = 0;
		cons.gridy = 0;
		cons.insets = new Insets(0, 10, 0, 10);
		cons.fill = GridBagConstraints.BOTH;
		headerPanel.add(logoLabel, cons);

		friendRequestsLabel.setFont(new java.awt.Font("Tahoma", 1, 11));
		friendRequestsLabel.setHorizontalAlignment(SwingConstants.CENTER);
		friendRequestsLabel.setIcon(new ImageIcon(getClass().getResource(
				"/fictional/GUI/resources/group.png"))); 
		friendRequestsLabel.setToolTipText("(0) Friend Requests");
		friendRequestsLabel.setCursor(new java.awt.Cursor(
				java.awt.Cursor.HAND_CURSOR));
		friendRequestsLabel.setHorizontalTextPosition(SwingConstants.RIGHT);
		friendRequestsLabel.setIconTextGap(0);
		friendRequestsLabel.setVerticalTextPosition(SwingConstants.BOTTOM);
		friendRequestsLabel.addMouseListener(new java.awt.event.MouseAdapter() {
			public void mouseClicked(java.awt.event.MouseEvent evt) {
				friendRequestsLabelMouseClicked(evt);
			}

			public void mouseEntered(java.awt.event.MouseEvent evt) {
				friendRequestsLabelMouseEntered(evt);
			}

			public void mouseExited(java.awt.event.MouseEvent evt) {
				friendRequestsLabelMouseExited(evt);
			}
		});

		cons.gridx = 1;
		headerPanel.add(friendRequestsLabel, cons);

		messagesLabel.setFont(new java.awt.Font("Tahoma", 1, 11));
		messagesLabel.setHorizontalAlignment(SwingConstants.CENTER);
		messagesLabel.setIcon(new ImageIcon(getClass().getResource(
				"/fictional/GUI/resources/comments.png"))); 
		messagesLabel.setToolTipText("(0) Messages");
		messagesLabel
				.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
		messagesLabel.setHorizontalTextPosition(SwingConstants.RIGHT);
		messagesLabel.setVerticalTextPosition(SwingConstants.BOTTOM);
		messagesLabel.setIconTextGap(0);
		messagesLabel.addMouseListener(new java.awt.event.MouseAdapter() {
			public void mouseEntered(java.awt.event.MouseEvent evt) {
				messagesLabelMouseEntered(evt);
			}

			public void mouseExited(java.awt.event.MouseEvent evt) {
				messagesLabelMouseExited(evt);
			}
			
			public void mouseClicked(java.awt.event.MouseEvent evt) {
				messagesLabelMouseClicked(evt);
			}
		});

		cons.gridx = 2;
		headerPanel.add(messagesLabel, cons);

		searchTextField.setBackground(new java.awt.Color(230, 235, 235));
		searchTextField.setText("Search");
		searchTextField.setEnabled(false);
		searchTextField.addMouseListener(new java.awt.event.MouseAdapter() {
			public void mouseClicked(java.awt.event.MouseEvent evt) {
				searchTextFieldMouseClicked(evt);
			}
		});
		searchTextField.addFocusListener(new java.awt.event.FocusAdapter() {
			public void focusGained(java.awt.event.FocusEvent evt) {
				searchTextFieldFocusGained(evt);
			}

			public void focusLost(java.awt.event.FocusEvent evt) {
				searchTextFieldFocusLost(evt);
			}
		});

		cons.gridx = 3;
		cons.ipadx = 80;
		cons.ipady = 5;
		cons.insets = new Insets(4, 0, 4, 10);
		headerPanel.add(searchTextField, cons);

		searchLabel.setIcon(new ImageIcon(getClass().getResource(
				"/fictional/GUI/resources/zoom.png"))); 
		searchLabel.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
		searchLabel.addMouseListener(new java.awt.event.MouseAdapter() {
			public void mouseClicked(java.awt.event.MouseEvent evt) {
				searchLabelMouseClicked(evt);
			}
		});

		cons.gridx = 4;
		cons.weightx = 1.0;
		cons.ipadx = 0;
		cons.ipady = 0;
		cons.insets = new Insets(0, 0, 0, 10);
		cons.anchor = GridBagConstraints.ABOVE_BASELINE_LEADING;
		headerPanel.add(searchLabel, cons);

		loggedInAsLabel.setFont(new java.awt.Font("Tahoma", 0, 11));
		loggedInAsLabel.setText("Logged in as " + loggedInCharacter.getName());

		cons.gridx = 5;
		cons.weightx = 0.0;
		cons.insets = new Insets(0, 10, 0, 10);
		headerPanel.add(loggedInAsLabel, cons);

		profileLabel.setFont(new java.awt.Font("Tahoma", 1, 11));
		profileLabel.setForeground(new java.awt.Color(74, 74, 74));
		profileLabel.setHorizontalAlignment(SwingConstants.CENTER);
		profileLabel.setText("Profile");
		profileLabel.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
		profileLabel.addMouseListener(new java.awt.event.MouseAdapter() {
			public void mouseClicked(java.awt.event.MouseEvent evt) {
				profileLabelMouseClicked(evt);
			}

			public void mouseEntered(java.awt.event.MouseEvent evt) {
				profileLabelMouseEntered(evt);
			}

			public void mouseExited(java.awt.event.MouseEvent evt) {
				profileLabelMouseExited(evt);
			}
		});

		cons.gridx = 6;
		headerPanel.add(profileLabel, cons);
		
		suggestedFriendsLabel.setFont(new java.awt.Font("Tahoma", 1, 11));
		suggestedFriendsLabel.setForeground(new java.awt.Color(74, 74, 74));
		suggestedFriendsLabel.setHorizontalAlignment(SwingConstants.CENTER);
		suggestedFriendsLabel.setText("Get Suggested Friends");
		suggestedFriendsLabel.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
		suggestedFriendsLabel.addMouseListener(new java.awt.event.MouseAdapter() {
			public void mouseClicked(java.awt.event.MouseEvent evt) {
				suggestedFriendsLabelMouseClicked(evt);
			}

			public void mouseEntered(java.awt.event.MouseEvent evt) {
				suggestedFriendsLabelMouseEntered(evt);
			}

			public void mouseExited(java.awt.event.MouseEvent evt) {
				suggestedFriendsLabelMouseExited(evt);
			}
		});

		cons.gridx = 7;
		headerPanel.add(suggestedFriendsLabel, cons);

		settingsLabel.setFont(new java.awt.Font("Tahoma", 1, 11));
		settingsLabel.setForeground(new java.awt.Color(74, 74, 74));
		settingsLabel.setHorizontalAlignment(SwingConstants.CENTER);
		settingsLabel.setIcon(new ImageIcon(getClass().getResource(
				"/fictional/GUI/resources/downButton.png"))); 
		settingsLabel.setText("Settings ");
		settingsLabel
				.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
		settingsLabel.setHorizontalTextPosition(SwingConstants.LEADING);
		settingsLabel.setMaximumSize(null);
		settingsLabel.setMinimumSize(null);
		settingsLabel.setPreferredSize(new java.awt.Dimension(67, 40));
		settingsLabel.addMouseListener(new java.awt.event.MouseAdapter() {
			public void mouseClicked(java.awt.event.MouseEvent evt) {
				settingsLabelMouseClicked(evt);
			}

			public void mouseEntered(java.awt.event.MouseEvent evt) {
				settingsLabelMouseEntered(evt);
			}

			public void mouseExited(java.awt.event.MouseEvent evt) {
				settingsLabelMouseExited(evt);
			}
		});

		cons.gridx = 8;
		cons.insets = new Insets(0, 10, 0, 0);
		headerPanel.add(settingsLabel, cons);

		getContentPane().add(headerPanel, java.awt.BorderLayout.NORTH);

		// END HEADER
	}

	private void initComponents() {
		
		headerPanel = new JPanel();
		logoLabel = new JLabel();
		settingsLabel = new JLabel();
		profileLabel = new JLabel();
		searchTextField = new JTextField();
		searchLabel = new JLabel();
		messagesLabel = new JLabel();
		friendRequestsLabel = new JLabel();
		leftPanel = new JPanel();
		leftPanelTabbedPane = new JTabbedPane();
		wallScrollPane = new JScrollPane();
		wallPanel = new JPanel();
		picturesScrollPane = new JScrollPane();
		picturesPanel = new JPanel();
		leftPanelTextLabel = new JLabel();
		leftPanelTextArea = new JTextArea();
		leftPanelButton = new JButton();
		rightPanel = new JPanel();
		nameLabel = new JLabel();
		statusLabel = new JLabel();
		genderIconLabel = new JLabel();
		genderLabel = new JLabel();
		speciesIconLabel = new JLabel();
		speciesLabel = new JLabel();
		organizationIconLabel = new JLabel();
		organizationLabel = new JLabel();
		friendsLabel = new JLabel();
		romanticIconLabel = new JLabel();
		romanticLabel = new JLabel();
		birthplaceIconLabel = new JLabel();
		birthplaceLabel = new JLabel();
		friendsPanel = new JPanel();
		rightPanelSeperator1 = new JSeparator();
		rightPanelSeperator2 = new JSeparator();
		rightPanelSeperator3 = new JSeparator();
		rightPanelSeperator4 = new JSeparator();
		rightPanelSeperator5 = new JSeparator();
		powersIconLabel = new JLabel();
		statusTextField = new JLabel();
		powersLabel = new JLabel();
		viewAllFriendsButton = new JButton();
		suggestedFriendsButton = new JButton();
		pokeMessagePanel = new JPanel();
		pokeButton = new JButton();
		messageButton = new JButton();
		imageLabel = new JLabel();
		loggedInAsLabel = new JLabel();
		editStatusLabel = new JLabel();
		characterInfoPanel = new JPanel();
		familyLabel = new JLabel();
		familyPanel = new JPanel();
		articleTextField = new JTextArea();
		addFriendButton = new JButton();
		articlePanel = new JPanel();
		profileImagePanel = new JPanel();
		occupationsLabel = new JLabel();
		occupationsIconLabel = new JLabel();
		suggestedFriendsLabel = new JLabel();
		viewAllFamilyButton = new JButton();
		statusPanel = new JPanel();
	}
	
	private void viewSuggestedFriends()
	{
		SearchFriendsTask searchFriendsTask = new SearchFriendsTask(Application.getInstance());
		searchFriendsTask.setSuggestTask(BL, this, loggedInCharacter);
		taskService.execute(searchFriendsTask);
		taskMonitor.setForegroundTask(searchFriendsTask);
		currentlyRunningTask = searchFriendsTask;
	}

	private void friendRequestsLabelMouseExited(java.awt.event.MouseEvent evt) {
		friendRequestsLabel.setBackground(headerPanel.getBackground());
		friendRequestsLabel.setOpaque(false);
	}

	private void friendRequestsLabelMouseEntered(java.awt.event.MouseEvent evt) {
		friendRequestsLabel.setBackground(friendsLabel.getBackground());
		friendRequestsLabel.setOpaque(true);
	}

	private void friendRequestsLabelMouseClicked(java.awt.event.MouseEvent evt) {
		if (friendRequestsItem.getRequests().size() == 0)
		{
			return;
		}
		
		friendRequests = new ArrayList<ShortCharacterItem>();

		if (currentResponse.isIs_Success()) {
			for (FriendRequestItem item : friendRequestsItem) {
				friendRequests.add(item.getSender());
			}
		}
		
		AddEditFriendsPopup popup = new AddEditFriendsPopup(friendRequests, ADD_FRIENDS, this, null, null);
		popup.setLocationRelativeTo(this);
		popup.setVisible(true);
	}

	private void messagesLabelMouseExited(java.awt.event.MouseEvent evt) {
		messagesLabel.setBackground(headerPanel.getBackground());
		messagesLabel.setOpaque(false);
	}

	private void messagesLabelMouseEntered(java.awt.event.MouseEvent evt) {
		messagesLabel.setBackground(friendsLabel.getBackground());
		messagesLabel.setOpaque(true);
	}

	private void searchLabelMouseClicked(java.awt.event.MouseEvent evt) {
		
		String searchedText = searchTextField.getText();
		if (searchedText.isEmpty() || searchedText.equals("Search")) {
			return;
		}
		
		startBusy();

		SearchFriendsTask searchFriendsTask = new SearchFriendsTask(Application.getInstance());
		searchFriendsTask.setSearchTask(BL, searchTextField.getText(), this, loggedInCharacter);
		taskService.execute(searchFriendsTask);
		taskMonitor.setForegroundTask(searchFriendsTask);
		currentlyRunningTask = searchFriendsTask;
	}

	private void searchTextFieldFocusLost(java.awt.event.FocusEvent evt) {
		searchTextField.setText("Search");
		searchTextField.setEnabled(false);
		searchTextField.setBackground(Color.getHSBColor(180f / 360, 0.02f,
				0.91f));
	}

	private void searchTextFieldFocusGained(java.awt.event.FocusEvent evt) {
		searchTextField.setText(null);
		searchTextField.setEnabled(true);
		searchTextField.setBackground(Color.getHSBColor(180f / 360, 0.04f,
				0.96f));
	}

	private void searchTextFieldMouseClicked(java.awt.event.MouseEvent evt) {
		searchTextField.requestFocus();
	}

	public void sendMessageButtonMouseClicked(java.awt.event.MouseEvent evt,
			ShortCharacterItem friend) {
		PrivateMessagePopup popup = new PrivateMessagePopup(friend, this);
		popup.setVisible(true);
	}

	private void profileLabelMouseExited(java.awt.event.MouseEvent evt) {
		profileLabel.setBackground(headerPanel.getBackground());
		profileLabel.setOpaque(false);
	}

	private void profileLabelMouseEntered(java.awt.event.MouseEvent evt) {
		profileLabel.setBackground(friendsLabel.getBackground());
		profileLabel.setOpaque(true);
	}

	private void settingsLabelMouseExited(java.awt.event.MouseEvent evt) {
		settingsLabel.setBackground(headerPanel.getBackground());
		settingsLabel.setOpaque(false);
	}

	private void settingsLabelMouseEntered(java.awt.event.MouseEvent evt) {
		settingsLabel.setBackground(friendsLabel.getBackground());
		settingsLabel.setOpaque(true);
	}

	private void settingsLabelMouseClicked(java.awt.event.MouseEvent evt) {
		settingsPopupMenu.show(settingsLabel, settingsLabel
				.getHorizontalAlignment(), settingsLabel.getHeight());
	}
	
	private void messagesLabelMouseClicked(java.awt.event.MouseEvent evt)
	{
		if (privateMessages.getAllMessages().size() == 0)
		{
			return;
		}
		ViewPrivateMessagesPopup popup = new ViewPrivateMessagesPopup(this, BL, privateMessages.getAllMessages());
		popup.setLocationRelativeTo(this);
		popup.setVisible(true);
	}
	
	private void suggestedFriendsLabelMouseClicked(MouseEvent evt) {
		viewSuggestedFriends();
	}
	
	private void suggestedFriendsLabelMouseEntered(java.awt.event.MouseEvent evt) {
		suggestedFriendsLabel.setBackground(friendsLabel.getBackground());
		suggestedFriendsLabel.setOpaque(true);
	}
	
	private void suggestedFriendsLabelMouseExited(java.awt.event.MouseEvent evt) {
		suggestedFriendsLabel.setBackground(headerPanel.getBackground());
		suggestedFriendsLabel.setOpaque(false);
	}

	private void deletePostButtonClicked(java.awt.event.MouseEvent evt,
			WallItem item) {
		AddDeleteWallPostTask wallTask = new AddDeleteWallPostTask(Application
				.getInstance());
		wallTask.setDeleteTask(BL, wall, item, this);
		taskService.execute(wallTask);
		taskMonitor.setForegroundTask(wallTask);
		currentlyRunningTask = wallTask;
	}


	public void sendFriendRequest(JButton button, ShortCharacterItem friend) {
		AddRemoveFriendTask friendRequestTask = new AddRemoveFriendTask(Application
				.getInstance());
		friendRequestTask.setRequestTask(BL, this, loggedInCharacter, friend, button);
		taskService.execute(friendRequestTask);
		taskMonitor.setForegroundTask(friendRequestTask);
		currentlyRunningTask = friendRequestTask;
	}

	public void approveFriendRequest(JButton button, JButton secondButton, ShortCharacterItem friend) {
		AddRemoveFriendTask approveFriendRequestTask = new AddRemoveFriendTask(Application
				.getInstance());
		approveFriendRequestTask.setApproveTask(BL, this, friendRequestsItem, friend, button, secondButton);
		taskService.execute(approveFriendRequestTask);
		taskMonitor.setForegroundTask(approveFriendRequestTask);
		currentlyRunningTask = approveFriendRequestTask;
	}

	public void ignoreFriendRequest(JButton button, JButton secondButton, ShortCharacterItem friend) {
		AddRemoveFriendTask task = new AddRemoveFriendTask(Application
				.getInstance());
		task.setIgnoreTask(BL, this, friendRequestsItem, friend, button, secondButton);
		taskService.execute(task);
		taskMonitor.setForegroundTask(task);
		currentlyRunningTask = task;
	}

	public void removeFriend(JButton button, ShortCharacterItem friend) {
		AddRemoveFriendTask task = new AddRemoveFriendTask(Application
				.getInstance());
		task.setRemoveTask(BL, this, loggedInCharacter, friend, button);
		taskService.execute(task);
		taskMonitor.setForegroundTask(task);
		currentlyRunningTask = task;
	}

	private void leftPanelTabbedPaneStateChanged(
			javax.swing.event.ChangeEvent evt) {
		// now looking at pictures tab
		if (leftPanelTabbedPane.getSelectedIndex() == 1) {
			
			if (isSameCharacter)
			{
				leftPanelButton.setEnabled(true);
			}
			else
			{
				leftPanelButton.setEnabled(false);
			}
			
			leftPanelTextLabel.setText("Insert URL:");
			leftPanelButton.setText("Add New Image");
			leftPanelTextArea.setPreferredSize(new Dimension(400, 50));
		}

		// now looking at wall
		if (leftPanelTabbedPane.getSelectedIndex() == 0) {
			leftPanelButton.setEnabled(true);
			leftPanelTextLabel.setText("Write On Wall:");
			leftPanelButton.setText("Share");
		}
	}
	
	private void viewImageMouseClicked(String link) {
		ViewImagePopup popup = new ViewImagePopup(link);
		popup.setLocationRelativeTo(this);
		popup.setVisible(true);
	}

	private void leftPanelButtonMouseClicked(java.awt.event.MouseEvent evt) {
		if (leftPanelTextArea.getText().equals("")) {
			return;
		}

		if (leftPanelTabbedPane.getSelectedIndex() == 0) {
			AddDeleteWallPostTask wallTask = new AddDeleteWallPostTask(
					Application.getInstance());
			wallTask.setAddTask(BL, loggedInCharacter, displayedCharacter,
					leftPanelTextArea.getText(), wall, this);
			taskService.execute(wallTask);
			taskMonitor.setForegroundTask(wallTask);
			currentlyRunningTask = wallTask;
			
		} else if (leftPanelTabbedPane.getSelectedIndex() == 1) {
			String imgLink = leftPanelTextArea.getText();

			try {
				@SuppressWarnings("unused")
				URL imgURL = new URL(imgLink);
			} catch (MalformedURLException ex) {
				JOptionPane.showMessageDialog(null,
						"The URL you have entered is not valid.",
						"Error Adding Image", JOptionPane.OK_OPTION);
				return;
			}

			AddRemovePictureTask pictureTask = new AddRemovePictureTask(Application
					.getInstance());
			pictureTask.setAddTask(BL, this, imgLink, loggedInCharacter);
			taskService.execute(pictureTask);
			taskMonitor.setForegroundTask(pictureTask);
			currentlyRunningTask = pictureTask;
		}
		
		leftPanelTextArea.setText("");
	}

	private void viewAllFriendsButtonMouseClicked(java.awt.event.MouseEvent evt) {
		AddEditFriendsPopup popup;
		if (displayedCharacter.getId() == loggedInCharacter.getId())
		{
			popup = new AddEditFriendsPopup(displayedCharacter
					.getFriends(), EDIT_FRIENDS, this, null, null);
		}
		else
		{
			popup = new AddEditFriendsPopup(displayedCharacter
					.getFriends(), VIEW_FRIENDS, this, null, null);
		}
		popup.setLocationRelativeTo(this);
		popup.setVisible(true);
	}
	
	private void viewAllFamilyButtonMouseClicked(java.awt.event.MouseEvent evt)
	{
		AddEditFriendsPopup popup = new AddEditFriendsPopup(displayedCharacter.getSiblings(), displayedCharacter.getChildren(), displayedCharacter.getMarriages(), this);
		popup.setLocationRelativeTo(this);
		popup.setVisible(true);
	}

	private void profileLabelMouseClicked(java.awt.event.MouseEvent evt) {
		if (!isSameCharacter) {
			ChangeDisplayedCharacterTask changeCharacterTask = new ChangeDisplayedCharacterTask(
					Application.getInstance());
			changeCharacterTask.setTask(BL, this, loggedInCharacter);
			taskService.execute(changeCharacterTask);
			taskMonitor.setForegroundTask(changeCharacterTask);
			currentlyRunningTask = changeCharacterTask;
		}
	}

	private void editStatusMouseClicked() {
		String input = JOptionPane.showInputDialog("Enter new status:");
		if (input != null) {
			if (!input.isEmpty())
			{
				EditStatusTask editStatusTask = new EditStatusTask(Application
						.getInstance());
				editStatusTask.setTask(BL, this, input, loggedInCharacter);
				taskService.execute(editStatusTask);
				taskMonitor.setForegroundTask(editStatusTask);
				currentlyRunningTask = editStatusTask;
			}
		}
	}

	private void imageMouseClicked(java.awt.event.MouseEvent evt, ImageItem image) {
		String[] buttons = { "Delete Image", "Set Profile Image", "View Image", "Cancel" };

	    int rc = JOptionPane.showOptionDialog(null, "What do you want to do?", "Image Selected",
	    		JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE, null, buttons, buttons[3]);
	    
	    if (rc == 0)
	    {
			AddRemovePictureTask removePictureTask = new AddRemovePictureTask(
					Application.getInstance());
			removePictureTask.setDeleteTask(BL, this, image, loggedInCharacter);
			taskService.execute(removePictureTask);
			taskMonitor.setForegroundTask(removePictureTask);
			currentlyRunningTask = removePictureTask;
	    }
	    else if (rc == 1)
	    {
			AddRemovePictureTask setProfileTask = new AddRemovePictureTask(
					Application.getInstance());
			setProfileTask.setProfileTask(BL, this, image, loggedInCharacter);
			taskService.execute(setProfileTask);
			taskMonitor.setForegroundTask(setProfileTask);
			currentlyRunningTask = setProfileTask;
	    }
	    else if (rc == 2)
	    {
	    	viewImageMouseClicked(image.getLink());
	    }
	}

	private void viewFriendMouseClicked(java.awt.event.MouseEvent evt,
			ShortCharacterItem friend) {
		int dialogResponse = JOptionPane.showConfirmDialog(null,
				"Are you sure you want to view " + friend.getName()
						+ "'s profile?", "Change View",
				JOptionPane.YES_NO_OPTION);
		if (dialogResponse == 0) {
			getCharacterForView(friend);
		}
	}

	public void getCharacterForView(ShortCharacterItem friend) {
		ChangeDisplayedCharacterTask changeCharacterTask = new ChangeDisplayedCharacterTask(
				Application.getInstance());
		changeCharacterTask.setTask(BL, this, friend);
		taskService.execute(changeCharacterTask);
		taskMonitor.setForegroundTask(changeCharacterTask);
		currentlyRunningTask = changeCharacterTask;
	}

	private void startBusy() {
		this.setEnabled(false);
		busyIconPopup.start();
	}

	private void stopBusy() {
		this.setEnabled(true);
		busyIconPopup.stop();
	}

	private javax.swing.JLabel birthplaceIconLabel;
	private javax.swing.JLabel birthplaceLabel;
	private javax.swing.JLabel friendRequestsLabel;
	private javax.swing.JLabel friendsLabel;
	private javax.swing.JPanel friendsPanel;
	private javax.swing.JLabel genderIconLabel;
	private javax.swing.JLabel genderLabel;
	private javax.swing.JPanel headerPanel;
	private javax.swing.JLabel imageLabel;
	private javax.swing.JPanel leftPanel;
	private javax.swing.JButton leftPanelButton;
	private javax.swing.JTabbedPane leftPanelTabbedPane;
	private javax.swing.JTextArea leftPanelTextArea;
	private javax.swing.JLabel leftPanelTextLabel;
	private javax.swing.JLabel logoLabel;
	private javax.swing.JButton messageButton;
	private javax.swing.JLabel messagesLabel;
	private javax.swing.JLabel nameLabel;
	private javax.swing.JLabel organizationIconLabel;
	private javax.swing.JLabel organizationLabel;
	private javax.swing.JPanel picturesPanel;
	private javax.swing.JScrollPane picturesScrollPane;
	private javax.swing.JButton pokeButton;
	private javax.swing.JPanel pokeMessagePanel;
	private javax.swing.JLabel powersIconLabel;
	private javax.swing.JLabel powersLabel;
	private javax.swing.JLabel profileLabel;
	private javax.swing.JPanel rightPanel;
	private javax.swing.JSeparator rightPanelSeperator1;
	private javax.swing.JSeparator rightPanelSeperator2;
	private javax.swing.JSeparator rightPanelSeperator4;
	private javax.swing.JSeparator rightPanelSeperator5;
	private javax.swing.JLabel romanticIconLabel;
	private javax.swing.JLabel romanticLabel;
	private javax.swing.JLabel searchLabel;
	private javax.swing.JTextField searchTextField;
	private javax.swing.JLabel settingsLabel;
	private javax.swing.JLabel speciesIconLabel;
	private javax.swing.JLabel speciesLabel;
	private javax.swing.JLabel statusTextField;
	private javax.swing.JButton viewAllFriendsButton;
	private javax.swing.JPanel wallPanel;
	private javax.swing.JScrollPane wallScrollPane;
	private final JPopupMenu settingsPopupMenu = new JPopupMenu();
	private JLabel loggedInAsLabel;
	private JLabel editStatusLabel;
	private JPanel characterInfoPanel;
	private JLabel familyLabel;
	private JPanel familyPanel;
	private JSeparator rightPanelSeperator3;
	private JTextArea articleTextField;
	private JButton addFriendButton;
	private JPanel articlePanel;
	private JPanel profileImagePanel;
	private JLabel occupationsLabel;
	private JLabel statusLabel;
	private JLabel occupationsIconLabel;
	private JLabel suggestedFriendsLabel;
	private JButton viewAllFamilyButton;
	private JButton suggestedFriendsButton;
	private JPanel statusPanel;

	private void initWindowLookAndFeel() {
		try {
			UIManager
					.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
		} catch (Exception e) {
			e.printStackTrace();
		}

		setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
		setTitle("Welcome to Ficbook");
		this.setSize(new Dimension(900, 700));
		this.setResizable(false);
		this.setLocationRelativeTo(null);
        this.setIconImage(new ImageIcon(getClass().getResource("resources/windowIcon.gif")).getImage());
	}

	private void initRightPanel()
    {
        friendRequestsSent = BL.getFriendRequests(loggedInCharacter, false, currentResponse);
        
		initInfoDisplay();
		
		initProfileImageDisplay();
        
        initFriendDisplay();
        
        initFamilyDisplay();
        
        initPokeMessagesFriendRequestDisplay();
        
        initArticleDisplay();
        
        if (isSameCharacter)
        {
        	suggestedFriendsButton.setVisible(true);
        }
        else
        {
        	suggestedFriendsButton.setVisible(false);
        }
    }

	private void initArticleDisplay() {
		
    	articlePanel.removeAll();
    	
    	GridBagConstraints cons = new GridBagConstraints();
    	
    	JScrollPane articleScrollPane = new JScrollPane();
    	articleScrollPane.setViewportView(articleTextField);
    	
        if (displayedCharacter.getArticle() != null && displayedCharacter.getArticle().getText() != null)
        {        
    		articleTextField.setBackground(new java.awt.Color(225, 237, 237));
    		articleTextField.setText(displayedCharacter.getArticle().getText());
   			articleTextField.setLineWrap(true);
    		articleTextField.setWrapStyleWord(true);
   			articleTextField.setEditable(false);
    		articleTextField.setOpaque(true);
    		articleTextField.setFont(new Font("Tahoma", Font.PLAIN, 12));
    		
    		cons.gridx = 0;
    		cons.gridy = 0;
    		cons.gridwidth = 2;
    		cons.weighty = 1.0;
    		cons.weightx = 1.0;
    		cons.fill = GridBagConstraints.BOTH;
    		cons.insets = new Insets(10, 10, 10, 10);
        }
        else
        {
    		articleTextField.setFont(new Font("Tahoma", Font.PLAIN, 12));
        	articleTextField.setText("No article available.");
        }
        
		articlePanel.add(articleScrollPane, cons);
		
		articlePanel.revalidate();
		articlePanel.repaint();
	}

	private void initPokeMessagesFriendRequestDisplay() {
		
    	pokeMessagePanel.removeAll();
    	GridBagConstraints cons = new GridBagConstraints();
    	
        if (!isSameCharacter)
        {    
    		cons.gridx = 0;
    		cons.gridy = 0;
    		cons.fill = GridBagConstraints.HORIZONTAL;
    		cons.anchor = java.awt.GridBagConstraints.NORTHWEST;
    		cons.insets = new java.awt.Insets(10, 10, 10, 10);
    		pokeMessagePanel.add(pokeButton, cons);
    		
    		cons.gridx = 1;
    		cons.anchor = java.awt.GridBagConstraints.NORTHWEST;
    		cons.insets = new java.awt.Insets(10, 10, 10, 10);
    		pokeMessagePanel.add(messageButton, cons);
    		
    		boolean disableFriendButton = false;
    		
    		for (ShortCharacterItem friend : loggedInCharacter.getFriends())
    		{
    			if (friend.getId() == displayedCharacter.getId())
    			{
    				disableFriendButton = true;
    				break;
    			}
    		}
    		if (!disableFriendButton)
    		{
    			for (FriendRequestItem friendRequest : friendRequestsSent)
    			{
    				if (friendRequest.getReceiver().getId() == displayedCharacter.getId())
    				{
        				disableFriendButton = true;
        				break;
    				}
    			}
    		}
    		if (!disableFriendButton)
    		{
    			for (FriendRequestItem friendRequest : friendRequestsItem)
    			{
    				if (friendRequest.getSender().getId() == displayedCharacter.getId())
    				{
        				disableFriendButton = true;
        				break;
    				}
    			}
    		}
    		
			cons = new java.awt.GridBagConstraints();
			cons.gridx = 2;
			cons.anchor = java.awt.GridBagConstraints.NORTHWEST;
			cons.insets = new java.awt.Insets(10, 10, 10, 10);
			
			if (!disableFriendButton)
			{
				addFriendButton.setEnabled(true);
			}
			else
			{
				addFriendButton.setEnabled(false);
			}
			
			pokeMessagePanel.add(addFriendButton, cons);
        }
        else
        {
        	cons.gridx = 0;
        	cons.gridy = 0;
        	cons.insets = new Insets(0, 10, 0, 10);
        	cons.anchor = GridBagConstraints.EAST;
        	
        	if (pokes.getPokes().isEmpty())
        	{
        		JLabel pokeLabel = new JLabel("No one has poked you yet!");
            	pokeMessagePanel.add(pokeLabel, cons);
        	}
        	else
        	{
            	final PokeItem poke = pokes.getPokes().first();
            	JLabel lastPokedByLabel = new JLabel("Poked by " + poke.getSender().getName());
            	JButton pokedBackButton = new JButton("Poke Back!");
            	pokedBackButton.setIcon(new ImageIcon(getClass().getResource(
    			"/fictional/GUI/resources/poke.png")));
            	
            	pokedBackButton.addMouseListener(new java.awt.event.MouseAdapter()
                {
                    public void mouseClicked(java.awt.event.MouseEvent evt)
                    {
                    	pokeCharacter(poke.getSender());
                    }
                });
            	pokeMessagePanel.add(lastPokedByLabel, cons);
            	cons.gridx = 1;
            	pokeMessagePanel.add(pokedBackButton, cons);	
        	}
        }
	}

	private void initFamilyDisplay() {
		
        familyPanel.removeAll();
    	int counter = 0;
    	ArrayList<ShortCharacterItem> charArray;
        
        if (!displayedCharacter.getSiblings().isEmpty() || !displayedCharacter.getChildren().isEmpty() || !displayedCharacter.getMarriages().isEmpty())
        {  	
        	if (!displayedCharacter.getSiblings().isEmpty())
        	{
                charArray = displayedCharacter.getSiblings();

                for (int i = 0; i < charArray.size(); i++)
                {
                	if (counter >= DISPLAYED_FRIENDS)
                	{
                		break;
                	}
                	
                    final ShortCharacterItem friend = charArray.get(i);                
                    JLabel friendLabel = getFriendLabel(friend);
                    
                    if (friendLabel != null)
                    {
                    	friendLabel.setToolTipText(friend.getName() + " (sibling)");
                    	friendLabel.setCursor(new Cursor(Cursor.HAND_CURSOR));
                        
                        familyPanel.add(friendLabel);
                        counter++;
                    }
                }
        	} 
        	else if (!displayedCharacter.getChildren().isEmpty())
        	{
                charArray = displayedCharacter.getChildren();
                
                for (int i = 0; i < charArray.size(); i++)
                {
                	if (counter >= DISPLAYED_FRIENDS)
                	{
                		break;
                	}
                	
                    final ShortCharacterItem friend = charArray.get(i);                
                    JLabel friendLabel = getFriendLabel(friend);
                    
                    if (friendLabel != null)
                    {
                    	friendLabel.setToolTipText(friend.getName() + " (child)");
                    	friendLabel.setCursor(new Cursor(Cursor.HAND_CURSOR));
                        
                        familyPanel.add(friendLabel);
                        counter++;
                    }
                }
        	}
        	else if (!displayedCharacter.getMarriages().isEmpty())
        	{
                charArray = displayedCharacter.getMarriages();
                
                for (int i = 0; i < charArray.size(); i++)
                {
                	if (counter >= DISPLAYED_FRIENDS)
                	{
                		break;
                	}
                	
                    final ShortCharacterItem friend = charArray.get(i);                
                    JLabel friendLabel = getFriendLabel(friend);
                    
                    if (friendLabel != null)
                    {
                    	friendLabel.setToolTipText(friend.getName() + " (married to)");
                    	friendLabel.setCursor(new Cursor(Cursor.HAND_CURSOR));
                        
                        familyPanel.add(friendLabel);
                        counter++;
                    }
                }
        	}
        }
        else
        {
        	JLabel noFamilyLabel = new JLabel("No listed family.");
        	familyPanel.add(noFamilyLabel);
        }
        
        familyPanel.add(viewAllFamilyButton);   

        if (counter < DISPLAYED_FRIENDS)
        {
        	viewAllFamilyButton.setVisible(false);
        }
        else
        {
        	viewAllFamilyButton.setVisible(true);
        }
        
        friendsPanel.revalidate();
        friendsPanel.repaint();
		
		if (toDraw)
		{
			(new ImageLoader(drawDataList)).execute();
		}
	}

	public void initProfileImageDisplay() {
		
        String imgURL;
        profileImagePanel.removeAll();
        
        if (displayedCharacter.getProfileImage() != null)
        {
            imgURL = displayedCharacter.getProfileImage().getLink();
        }
        else if (displayedCharacter.getId() == loggedInCharacter.getId() && loggedInCharacter.getProfileImage() != null) {
        	imgURL = loggedInCharacter.getProfileImage().getLink();
        } 
        else {
        	URL link = getClass().getResource("resources/defaultProfileImage.jpg");
            imgURL = link.toString();
        }
        
        imageLabel = getImageLabel(imgURL, 145, 185);
        profileImagePanel.add(imageLabel);
        
        if (toDraw)
        {
        	(new ImageLoader(drawDataList)).execute();
        }
        
        profileImagePanel.revalidate();
        profileImagePanel.repaint();
	}

	public void initFriendDisplay() {
		
        friendsPanel.removeAll();
        
        ArrayList<ShortCharacterItem> friendsArray = new ArrayList<ShortCharacterItem>();
        
        friendsLabel.setText("FRIENDS (" + displayedCharacter.getFriends().size() + ")");
        friendsLabel.setFont(new Font("Tahoma", Font.BOLD, 11));
        
        if (!displayedCharacter.getFriends().isEmpty())
        {
            friendsArray = getDisplayedFriends();

            for (int i = 0; i < friendsArray.size(); i++)
            {
                final ShortCharacterItem friend = friendsArray.get(i);                
                JLabel friendLabel = getFriendLabel(friend);
                
                if (friendLabel != null)
                {
                	friendLabel.setToolTipText(friend.getName());
                    
                    friendsPanel.add(friendLabel);
                }
            }
         
        }
        else
        {
        	JLabel noFriendsLabel = new JLabel("No listed friends.");
        	friendsPanel.add(noFriendsLabel);
        }
        
        if (displayedCharacter.getFriends().size() > DISPLAYED_FRIENDS)
        {
            friendsPanel.add(viewAllFriendsButton);   
        }
        
        friendsPanel.revalidate();
        friendsPanel.repaint();
		
		if (toDraw)
		{
			(new ImageLoader(drawDataList)).execute();
		}
	}

	public void initInfoDisplay() {
		
        nameLabel.setText(displayedCharacter.getName());
        nameLabel.setToolTipText(nameLabel.getText());
        
        // set character's gender
        if (displayedCharacter.getGender() != null)
        {
        	if (displayedCharacter.getGender().getGender() != null)
        	{
        		genderLabel.setText(displayedCharacter.getGender().getGender());
        		genderIconLabel.setIcon(new ImageIcon(getClass().getResource("resources/genderIconLabelImage.png")));
                genderLabel.setFont(new Font("Tahoma", Font.PLAIN, 11));
                genderLabel.setForeground(Color.black);
                genderLabel.setToolTipText(genderLabel.getText());
        	}
        else
        {
        	genderLabel.setText("unknown");
            genderIconLabel.setIcon(new ImageIcon(getClass().getResource("resources/gender_disabled.png")));
            genderLabel.setFont(new Font("Tahoma", Font.ITALIC, 11));
            genderLabel.setForeground(Color.gray);
            genderLabel.setToolTipText(null);
        }
        }

        //set character's species
        if (displayedCharacter.getSpecies() != null)
        {
        	if (displayedCharacter.getSpecies().getSpecies() != null)
        	{
        		 speciesLabel.setText(displayedCharacter.getSpecies().getSpecies());
        		 speciesIconLabel.setIcon(new ImageIcon(getClass().getResource("resources/speciesIconLabelImage.gif")));
        		 speciesLabel.setFont(new Font("Tahoma", Font.PLAIN, 11));
        		 speciesLabel.setForeground(Color.black);
        		 speciesLabel.setToolTipText(speciesLabel.getText());
        	}
        else
        {
        	speciesLabel.setText("unknown");
            speciesIconLabel.setIcon(new ImageIcon(getClass().getResource("resources/species_disabled.png")));
            speciesLabel.setFont(new Font("Tahoma", Font.ITALIC, 11));
            speciesLabel.setForeground(Color.gray);
            speciesLabel.setToolTipText(null);
           
        }
        }

		// set character's organization
		if (displayedCharacter.getOrganizations() != null) 
		{
			if (!displayedCharacter.getOrganizations().isEmpty()) 
			{
                String organizations = "";
                for (OrganizationItem organization : displayedCharacter.getOrganizations())
                {
                	organizations = organizations.concat(organization.getName() + ", ");
                }
                if (organizations.isEmpty())
                {
    				organizationLabel.setText("unknown");
                	organizationIconLabel.setIcon(new ImageIcon(getClass().getResource("resources/briefcase.png_disabled.png")));
                    organizationLabel.setFont(new Font("Tahoma", Font.ITALIC, 11));
                    organizationLabel.setForeground(Color.gray);
                	organizationLabel.setToolTipText(null);
                }
                else
                {
                	organizations = organizations.substring(0, organizations.length() - 2);
                	organizationIconLabel.setIcon(new ImageIcon(getClass().getResource("resources/briefcase.png")));
                	organizationLabel.setText(organizations);
                	organizationLabel.setFont(new Font("Tahoma", Font.PLAIN, 11));
                	organizationLabel.setForeground(Color.black);
                    organizationLabel.setToolTipText(organizationLabel.getText());
                }
			}
			else 
			{
				organizationLabel.setText("unknown");
				organizationIconLabel.setIcon(new ImageIcon(getClass()
						.getResource("resources/briefcase_disabled.png")));
				organizationLabel.setFont(new Font("Tahoma", Font.ITALIC, 11));
				organizationLabel.setForeground(Color.gray);
            	organizationLabel.setToolTipText(null);
			}
		}

		// set character's romantic involvement
		if (displayedCharacter.getRomantics() != null) 
		{
			if (!displayedCharacter.getRomantics().isEmpty()) 
			{
				romanticLabel.setText(displayedCharacter.getRomantics().get(0)
						.getName());
				romanticIconLabel.setIcon(new ImageIcon(getClass().getResource("resources/heart.png")));
				romanticLabel.setFont(new Font("Tahoma", Font.PLAIN, 11));
				romanticLabel.setForeground(Color.black);
				romanticLabel.setToolTipText(romanticLabel.getText());
			} 
			else 
			{
				romanticLabel.setText("unknown");
				romanticIconLabel.setIcon(new ImageIcon(getClass().getResource(
						"resources/heart_disabled.png")));
				romanticLabel.setFont(new Font("Tahoma", Font.ITALIC, 11));
				romanticLabel.setForeground(Color.gray);
				romanticLabel.setToolTipText(null);
			}
		}

        //set character's place of birth
        if (displayedCharacter.getPlace_of_birth() != null)
        {
        	if (displayedCharacter.getPlace_of_birth().getPlace() != null)
        	{
        		birthplaceLabel.setText(displayedCharacter.getPlace_of_birth().getPlace());
        		birthplaceIconLabel.setIcon(new ImageIcon(getClass().getResource("resources/world.png")));
        		birthplaceLabel.setFont(new Font("Tahoma", Font.PLAIN, 11));
        		birthplaceLabel.setForeground(Color.black);
        		birthplaceLabel.setToolTipText(birthplaceLabel.getText());
        	}
        else
        {
        	birthplaceLabel.setText("unknown");
            birthplaceIconLabel.setIcon(new ImageIcon(getClass().getResource("resources/world_disabled.png")));
            birthplaceLabel.setFont(new Font("Tahoma", Font.ITALIC, 11));
            birthplaceLabel.setForeground(Color.gray);
            birthplaceLabel.setToolTipText(null);
        }
        }

        //set character's power
        if (displayedCharacter.getPowers() != null)
        {
        	if (!displayedCharacter.getPowers().isEmpty())
        	{
                String powers = "";
                for (PowerItem power : displayedCharacter.getPowers())
                {
                	powers = powers.concat(power.getPower() + ", ");
                }
                if (powers.isEmpty())
                {
                    powersLabel.setText("unknown");
                    powersIconLabel.setIcon(new ImageIcon(getClass().getResource("resources/powers_disabled.png")));
                    powersLabel.setFont(new Font("Tahoma", Font.ITALIC, 11));
                    powersLabel.setForeground(Color.gray);
                    powersLabel.setToolTipText(null);
                }
                else
                {
                	powers = powers.substring(0, powers.length() - 2);
                	powersIconLabel.setIcon(new ImageIcon(getClass().getResource("resources/lightning.png")));
                    powersLabel.setText(powers);
                    powersLabel.setFont(new Font("Tahoma", Font.PLAIN, 11));
                    powersLabel.setForeground(Color.black);
                    powersLabel.setToolTipText(powersLabel.getText());
                }
        	}
        else
        {
            powersLabel.setText("unknown");
            powersIconLabel.setIcon(new ImageIcon(getClass().getResource("resources/powers_disabled.png")));
            powersLabel.setFont(new Font("Tahoma", Font.ITALIC, 11));
            powersLabel.setForeground(Color.gray);
            powersLabel.setToolTipText(null);
        }
        }
        
        if (displayedCharacter.getOccupations() != null)
        {
        	if (!displayedCharacter.getOccupations().isEmpty())
        	{
                String occupations = "";
                for (OccupationItem occupation : displayedCharacter.getOccupations())
                {
                	occupations = occupations.concat(occupation.getOccupation() + ", ");
                }
                if (occupations.isEmpty())
                {
                	occupationsLabel.setText("unknown");
                	occupationsIconLabel.setIcon(new ImageIcon(getClass().getResource("resources/wrench_disabled.png")));
                    occupationsLabel.setFont(new Font("Tahoma", Font.ITALIC, 11));
                    occupationsLabel.setForeground(Color.gray);
                	occupationsLabel.setToolTipText(null);
                }
                else
                {
                	occupations = occupations.substring(0, occupations.length() - 2);
                    occupationsIconLabel.setIcon(new ImageIcon(getClass().getResource("resources/wrench.png")));
                	occupationsLabel.setText(occupations);
                	occupationsLabel.setFont(new Font("Tahoma", Font.PLAIN, 11));
                	occupationsLabel.setForeground(Color.black);
                    occupationsLabel.setToolTipText(occupationsLabel.getText());
                }
        	}
        else
        {
        	occupationsLabel.setText("unknown");
        	occupationsIconLabel.setIcon(new ImageIcon(getClass().getResource("resources/wrench_disabled.png")));
        	occupationsLabel.setFont(new Font("Tahoma", Font.ITALIC, 11));
        	occupationsLabel.setForeground(Color.gray);
        	occupationsLabel.setToolTipText(null);
        }
        }
        
        statusPanel.removeAll();
        
        statusTextField.setText(displayedCharacter.getStatus()); 
        statusTextField.setToolTipText(statusTextField.getText());
        
        GridBagConstraints cons = new GridBagConstraints();
        cons.gridx = 0;
        cons.gridy = 0;
        cons.weightx = 1.0;
        cons.insets = new Insets(10, 10, 0, 0);
        cons.anchor = GridBagConstraints.WEST;
        statusPanel.add(statusTextField, cons);
        
        if (isSameCharacter)
        {
            cons.gridx = 1;
            cons.weightx = 0.0;
            cons.insets = new Insets(10, 10, 0, 10);
            statusPanel.add(editStatusLabel, cons);
        }
	}

	private void initHeader() {
		
		initFriendRequestsMessagesPokes();
		
		initSettingsMenu();
		
		initFriendRequests();
		
		initPrivateMessagesHeader();
	}

	private void initSettingsMenu() {
		ActionListener menuListener = new ActionListener() {
			public void actionPerformed(ActionEvent event) {
				String action = event.getActionCommand();

				if (action.equalsIgnoreCase("About")) {
					AboutPopup popup = new AboutPopup(GUI.this);
					popup.setLocationRelativeTo(null);
					popup.setVisible(true);
				}
				if (action.equalsIgnoreCase("Edit Friends")) {
					AddEditFriendsPopup popup = new AddEditFriendsPopup(
							loggedInCharacter.getFriends(), EDIT_FRIENDS,
							GUI.this, null, null);
					popup.setLocationRelativeTo(GUI.this);
					popup.setVisible(true);
				}
				if (action.equalsIgnoreCase("Edit Information")) 
				{
					editInformationMouseClicked();
				}
				if (action.equalsIgnoreCase("Logout")) {
					int response = JOptionPane.showConfirmDialog(null,
							"Are you sure you want to log out?", "Logout",
							JOptionPane.YES_NO_OPTION);
					if (response == JOptionPane.OK_OPTION) {
						login.loggedOut();
					}
				}
			}

			private void editInformationMouseClicked()
			{
				EditInfoPopup popup = new EditInfoPopup(GUI.this, BL,
						loggedInCharacter.getGender(), loggedInCharacter.getSpecies(),
						loggedInCharacter.getOrganizations(), loggedInCharacter.getPlace_of_birth(), loggedInCharacter.getOccupations(), loggedInCharacter.getPowers());
				popup.setLocationRelativeTo(GUI.this);
				popup.setVisible(true);
			}
		};

		JMenuItem aboutItem = new JMenuItem("About");
		JMenuItem editFriendsItem = new JMenuItem("Edit Friends");
		if (loggedInCharacter.getFriends().isEmpty()) {
			editFriendsItem.setEnabled(false);
		}
		JMenuItem editInfoItem = new JMenuItem("Edit Information");
		JSeparator seperator = new JSeparator();
		JMenuItem logoutItem = new JMenuItem("Logout");

		aboutItem.addActionListener(menuListener);
		editFriendsItem.addActionListener(menuListener);
		editInfoItem.addActionListener(menuListener);
		logoutItem.addActionListener(menuListener);
		settingsPopupMenu.add(aboutItem);
		settingsPopupMenu.add(editFriendsItem);
		settingsPopupMenu.add(editInfoItem);
		settingsPopupMenu.add(seperator);
		settingsPopupMenu.add(logoutItem);

	}

	private void initFriendRequests() {
		int numOfFriendRequests = friendRequestsItem.getRequests().size();

		if (numOfFriendRequests > 0) {
			friendRequestsLabel.setIcon(new ImageIcon(getClass().getResource(
					"resources/group_add.png")));
			friendRequestsLabel.setToolTipText("(" + numOfFriendRequests
					+ ") Friend Requests");
			friendRequestsLabel.setText("" + numOfFriendRequests);
		}
	}

	private void initPrivateMessagesHeader() 
	{
		int numOfMessages = privateMessages.getAllMessages().size();

		if (numOfMessages > 0) {
			messagesLabel.setIcon(new ImageIcon(getClass().getResource(
					"resources/comments_add.png")));
			messagesLabel.setToolTipText("(" + numOfMessages
					+ ") Messages");
			messagesLabel.setText("" + numOfMessages);
		}
	}

	private void initLeftPanel() {
		
		leftPanelTextArea.requestFocusInWindow();
		
		if (leftPanelTabbedPane.getSelectedIndex() == 0)
		{
			leftPanelButton.setEnabled(true);
		}
		else
		{
			if (isSameCharacter)
			{
				leftPanelButton.setEnabled(true);
			}
			else
			{
				leftPanelButton.setEnabled(false);
			}
		}
		
		initWall();
		
		initPictures();
	}

	public void initPictures() {
		
		GridBagLayout gridLayout = new GridBagLayout();
		picturesPanel.removeAll();
		picturesPanel.setLayout(gridLayout);

		GridBagConstraints cons = new GridBagConstraints();
		cons.fill = GridBagConstraints.HORIZONTAL;
		cons.gridwidth = 1;
		cons.insets = new Insets(20, 0, 0, 20);
		cons.anchor = GridBagConstraints.NORTHWEST;
		int imgCount = 0;

		for (final ImageItem image : displayedCharacter.getImages()) {
			JLabel currImageLabel = getImageLabel(image.getLink(), 120, 100);

			if (currImageLabel != null) {
				cons.gridx = imgCount % 3;
				cons.gridy = imgCount / 3;

				if (loggedInCharacter.getId() == displayedCharacter.getId())
				{
					currImageLabel
					.addMouseListener(new java.awt.event.MouseAdapter() {
						public void mouseClicked(
								java.awt.event.MouseEvent evt) {
							imageMouseClicked(evt, image);
						}
					});
					
					currImageLabel.setCursor(new Cursor(Cursor.HAND_CURSOR));
				}
				else
				{
					currImageLabel
					.addMouseListener(new java.awt.event.MouseAdapter() {
						public void mouseClicked(
								java.awt.event.MouseEvent evt) {
							viewImageMouseClicked(image.getLink());
						}
					});
					
					currImageLabel.setCursor(new Cursor(Cursor.HAND_CURSOR));
				}

				if (displayedCharacter.getImages().indexOf(image) == displayedCharacter
						.getImages().size() - 1) {
					cons.weighty = 1.0;
				}

				currImageLabel.setName(image.getLink());
				picturesPanel.add(currImageLabel, cons);
				imgCount++;
			}
		}
		
		if (toDraw)
		{
			(new ImageLoader(drawDataList)).execute();
		}
		
		picturesPanel.revalidate();
		picturesPanel.repaint();
	}

	public void initWall() {
		
		GridBagLayout gridLayout = new GridBagLayout();
		wallPanel.removeAll();
		wallPanel.setLayout(gridLayout);

		GridBagConstraints cons = new GridBagConstraints();
		cons.fill = GridBagConstraints.HORIZONTAL;
		cons.anchor = GridBagConstraints.NORTH;
		cons.insets = new Insets(20, 20, 0, 0);
		int wallCount = 0;

		if (getWall() == null) {
			// ERROR
		} else {

			SortedSet<WallItem> posts = getWall().getWallPosts();

			if (!posts.isEmpty()) {
				for (final WallItem item : posts) {
					JLabel friendImageLabel = getFriendLabel(item.getPoster());

					cons.gridx = 0;
					cons.gridy = wallCount;
					cons.gridheight = 3;
					cons.gridwidth = 1;
					cons.insets = new Insets(20, 20, 0, 0);
					wallPanel.add(friendImageLabel, cons);

					JLabel nameLabel = new JLabel(item.getPoster().getName()
							.toUpperCase());
					nameLabel.setFont(new Font("Tahoma", Font.BOLD, 11));
					cons.gridx = 1;
					cons.gridy = wallCount;
					cons.gridheight = 1;
					cons.weightx = 1.0;
					cons.insets = new Insets(20, 20, 0, 10);
					wallPanel.add(nameLabel, cons);

					JTextArea wallText = new JTextArea(item.getText());
					wallText.setLineWrap(true);
					wallText.setWrapStyleWord(true);
					wallText.setEditable(false);
					wallText.setFont(new Font("Tahoma", Font.PLAIN, 11));
					cons.gridx = 1;
					cons.gridy = wallCount + 1;
					cons.gridheight = 1;
					cons.weightx = 1.0;
					cons.gridwidth = 2;
					cons.insets = new Insets(10, 20, 0, 10);
					wallPanel.add(wallText, cons);

					JLabel wallDate = new JLabel(item.getDate().toString());
					wallDate.setForeground(Color.GRAY);
					cons.gridx = 1;
					cons.gridy = wallCount + 2;
					cons.weightx = 0;
					cons.gridwidth = 1;
					cons.insets = new Insets(20, 20, 0, 0);
					wallPanel.add(wallDate, cons);

					if (isSameCharacter)
					{
						JButton deleteButton = new JButton("Delete Post");
						cons.gridx = 2;
						cons.gridy = wallCount + 2;
						cons.weightx = 0;
						cons.insets = new Insets(20, 20, 0, 20);
						wallPanel.add(deleteButton, cons);

						deleteButton
								.addMouseListener(new java.awt.event.MouseAdapter() {
									public void mouseClicked(
											java.awt.event.MouseEvent evt) {
										deletePostButtonClicked(evt, item);
									}
								});
					}
					
					if (posts.last() == item) {
						cons.weighty = 1.0;
					}

					JSeparator seperator = new JSeparator();
					cons.gridx = 0;
					cons.gridy = wallCount + 3;
					if (isSameCharacter)
					{
						cons.gridwidth = 3;
					}
					else
					{
						cons.gridwidth = 2;
					}
					cons.insets = new Insets(20, 20, 0, 20);
					wallPanel.add(seperator, cons);

					wallCount += 4;
				}
			}
			if (toDraw)
			{
				(new ImageLoader(drawDataList)).execute();
			}
		}
		
		wallPanel.revalidate();
		wallPanel.repaint();
	}

	private ArrayList<ShortCharacterItem> getDisplayedFriends() {
		if (displayedCharacter.getFriends() == null) {
			return null;
		}

		int count = 0;
		ArrayList<ShortCharacterItem> ret = new ArrayList<ShortCharacterItem>();

		for (ShortCharacterItem friend : displayedCharacter.getFriends()) {
			ret.add(friend);
			count++;
			if (count >= DISPLAYED_FRIENDS) {
				return ret;
			}
		}

		return ret;
	}

	private JLabel getImageLabel(String imgLink, int height, int width) {
		JLabel retImageLabel = new javax.swing.JLabel();
		retImageLabel.setBorder(javax.swing.BorderFactory
				.createLineBorder(new java.awt.Color(0, 0, 0)));
		retImageLabel.setPreferredSize(new java.awt.Dimension(height, width));
		
		java.net.URL imgURL;
		try {
			imgURL = new java.net.URL(imgLink);
		} catch (MalformedURLException e) {
			System.err.println("Error loading url " + imgLink);
			return null;
		}
		
		DrawData drawData = new DrawData(retImageLabel, imgURL, height, width);
		drawDataList.add(drawData);

		return retImageLabel;
	}

	public JLabel getFriendLabel(final ShortCharacterItem friend) {
        JLabel friendImageLabel = new javax.swing.JLabel();
        friendImageLabel.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
        friendImageLabel.setPreferredSize(new java.awt.Dimension(50, 50));
        friendImageLabel.setName("friendLabel" + friend.getId());
        
        friendImageLabel.setCursor(new Cursor(Cursor.HAND_CURSOR));
        
        friendImageLabel.addMouseListener(new java.awt.event.MouseAdapter()
        {
            public void mouseClicked(java.awt.event.MouseEvent evt)
            {
                viewFriendMouseClicked(evt, friend);
            }
        });
        
        java.net.URL imgURL = null;
        
        if (friend.getProfileImage() == null)
        {
        	imgURL = getClass().getResource("resources/defaultProfileImage.jpg");
        }
        else 
        {
            try
            {
                imgURL = new java.net.URL(friend.getProfileImage().getLink());
            } 
            catch (MalformedURLException e)
            {
            	imgURL = getClass().getResource("resources/defaultProfileImage.jpg");
            }	
        }

        DrawData drawData = new DrawData(friendImageLabel, imgURL, 50, 50);
        drawDataList.add(drawData);

        return friendImageLabel;
	}

	public void drawNewImage(String imgURL) {
		GridBagConstraints cons = new GridBagConstraints();
		cons.fill = GridBagConstraints.HORIZONTAL;
		cons.gridwidth = 1;
		cons.insets = new Insets(20, 0, 0, 20);
		cons.anchor = GridBagConstraints.NORTH;

		int imgCount = loggedInCharacter.getImages().size();
		JLabel friendImageLabel = new javax.swing.JLabel();
		friendImageLabel.setBorder(javax.swing.BorderFactory
				.createCompoundBorder(javax.swing.BorderFactory
						.createLineBorder(new java.awt.Color(0, 0, 0)),
						javax.swing.BorderFactory.createLineBorder(
								new java.awt.Color(255, 255, 255), 3))); 
		friendImageLabel.setPreferredSize(new java.awt.Dimension(120, 100));
		ImageIcon friendImage = (new ImageIcon(imgURL));
		friendImageLabel.setIcon(new ImageIcon(friendImage.getImage()
				.getScaledInstance(120, 100, 0)));
		friendImageLabel.setCursor(new Cursor(Cursor.HAND_CURSOR));

		cons.gridx = (imgCount % 3) - 1;
		cons.gridy = imgCount / 3;

		picturesPanel.add(friendImageLabel, cons);
		picturesPanel.revalidate();
		picturesPanel.repaint();
	}

	private Wall getWall() {
		currentResponse = new Response();
		wall = BL.getWall(displayedCharacter, currentResponse);

		if (!currentResponse.isIs_Success()) {
			wall = null;
		}

		return wall;
	}

	public void editInfo(GenderItem gender, SpeciesItem species, String organization,
			PlaceItem birthPlace, String occupations, String superPowers) {
		AddEditUserTask editInfoTask = new AddEditUserTask(Application.getInstance());
		editInfoTask.setTask(BL, this, loggedInCharacter, gender, species, organization,
				birthPlace, occupations, superPowers);
		taskService.execute(editInfoTask);
		taskMonitor.setForegroundTask(editInfoTask);
		currentlyRunningTask = editInfoTask;
	}

	public void searchFriends(ArrayList<ShortCharacterItem> searchResults, FriendRequests friendRequestsSent, FriendRequests friendRequestsReceived) {
		SortedSet<Integer> friendCannotBeAdded = new TreeSet<Integer>();
		for (FriendRequestItem request : friendRequestsSent)
		{
			friendCannotBeAdded.add(request.getReceiver().getId());
		}
		for (FriendRequestItem request : friendRequestsReceived)
		{
			friendCannotBeAdded.add(request.getSender().getId());
		}
		AddEditFriendsPopup popup = new AddEditFriendsPopup(searchResults,
				SEARCH_FRIENDS, this, friendCannotBeAdded, loggedInCharacter.getFriends());
		popup.setLocationRelativeTo(this);
		popup.setVisible(true);
	}

	private void initFriendRequestsMessagesPokes() {
		currentResponse = new Response();
		
		friendRequestsItem = BL.getFriendRequests(
				loggedInCharacter, true, currentResponse);

		currentResponse = new Response();
		privateMessages = BL.getMessages(loggedInCharacter, true,
				currentResponse);
		
		currentResponse = new Response();
		pokes = BL.getPokes(loggedInCharacter, currentResponse);
	}
	
	public void sendPrivateMessage(String message, ShortCharacterItem friend) {
		SendDeleteMessageTask sendMessageTask = new SendDeleteMessageTask(Application
				.getInstance());
		sendMessageTask.setSendTask(BL, loggedInCharacter, friend,
				message, this);
		taskService.execute(sendMessageTask);
		taskMonitor.setForegroundTask(sendMessageTask);
		currentlyRunningTask = sendMessageTask;
	}
	
	public void deletePrivateMessage(MessageItem message, JButton button)
	{
		SendDeleteMessageTask deleteMessageTask = new SendDeleteMessageTask(Application
				.getInstance());
		deleteMessageTask.setDeleteTask(BL, message, privateMessages, this, button);
		taskService.execute(deleteMessageTask);
		taskMonitor.setForegroundTask(deleteMessageTask);
		currentlyRunningTask = deleteMessageTask;
	}

	public void updateStatus(String newStatus) {
		statusTextField.setText(newStatus);
		statusTextField.setToolTipText(statusTextField.getText());
	}
	
	private void pokeCharacter(ShortCharacterItem friend)
	{
		PokeTask pokeTask = new PokeTask(Application.getInstance());
		pokeTask.setTask(BL, this, friend, loggedInCharacter);
		taskService.execute(pokeTask);
		taskMonitor.setForegroundTask(pokeTask);
		currentlyRunningTask = pokeTask;
	}
	
	public void deletePrivateMessageView()
	{
		if (!messagesLabel.getText().isEmpty())
		{
			int privateMessagesNum = Integer.parseInt(messagesLabel.getText());
			if (privateMessagesNum > 1)
			{
				messagesLabel.setText("" + (privateMessagesNum - 1));
			}
			else
			{
				messagesLabel.setIcon(new ImageIcon(getClass().getResource(
				"/fictional/GUI/resources/comments.png")));
				messagesLabel.setText("");
			}
		}
	}
	
	public void deleteFriendRequestView()
	{
		if (friendRequestsItem.getRequests().size() == 0)
		{
			friendRequestsLabel.setIcon(new ImageIcon(getClass().getResource(
					"/fictional/GUI/resources/group.png")));
					friendRequestsLabel.setText("");
					friendRequestsLabel.setToolTipText("(0) Friend Requests");
		}
		else
		{
			friendRequestsLabel.setIcon(new ImageIcon(getClass().getResource(
			"/fictional/GUI/resources/group_add.png")));
			friendRequestsLabel.setText("" + friendRequestsItem.getRequests().size());
			friendRequestsLabel.setToolTipText("(" + friendRequestsItem.getRequests().size() + ") Friend Requests");
		}
	}
	
    public void drawErrorMessage(String errorMessage, String errorTitle)
    {
    	JOptionPane.showMessageDialog(null, errorMessage, errorTitle, JOptionPane.OK_OPTION);
    }
    
	private void doInCaseOfDisconnection()
	{
		String[] buttons = { "Try Reconnecting", "Exit Program" };

	    int rc = JOptionPane.showOptionDialog(null, "Connection with satabase server has been closed. What would you like to do?", "Connection Error",
	    		JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE, null, buttons, buttons[1]);
	    
	    if (rc == 0)
	    {
	    	BL = login.reconnect();
	    	if (BL == null)
	    	{
	    		doInCaseOfDisconnection();
	    	}
	    	else
	    	{
	    		JOptionPane.showMessageDialog(null, "Connection re-established successfully.", "Operation Successful", JOptionPane.INFORMATION_MESSAGE);
	    	}
	    }
	    else if (rc == 1)
	    {
	    	this.setVisible(false);
	    	this.dispose();
	    	System.exit(0);
	    }
	}
}
